package com.lijinjiang.view;

import com.lijinjiang.model.GlobalContext;
import com.lijinjiang.model.ViewObject;
import com.lijinjiang.model.tree.*;

import javax.swing.*;
import javax.swing.Timer;
import javax.swing.tree.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.*;
import java.util.List;

/**
 * @ClassName LeftPane
 * @Description 主页面的左边面板
 * @Author Li
 * @Date 2022/8/15 13:58
 * @ModifyDate 2022/8/15 13:58
 * @Version 1.0
 */
public class LeftPane extends JScrollPane {
    // 全局上下文环境
    private GlobalContext ctx;

    // 主界面
    private MainFrame mainFrame;

    // 右面板
    private RightPane rightPane;

    // 树的右键弹出菜单
    private TreeMenu treeMenu;

    // 结构树：树的第一层子节点是各个连接，第二层子节点是该连接下的数据库列表，第三层子节点是表、视图等
    private JTree tree;

    public JTree getTree() {
        return tree;
    }

    public void setTree(JTree tree) {
        this.tree = tree;
    }

    // 树的Model
    private DefaultTreeModel treeModel;

    public DefaultTreeModel getTreeModel() {
        return treeModel;
    }

    // 对象面板的数据
    private Object[] emptyObjects = new Object[]{};
    private Object[] objects = new Object[]{};

    /* 构造TreePane面板 */
    public LeftPane(GlobalContext ctx, MainFrame mainFrame) {
        this.ctx = ctx;
        this.mainFrame = mainFrame;
        this.setBorder(null); // 不设置该组件边框
        createTree(); // 初始化树对象
        this.treeMenu = new TreeMenu(ctx, mainFrame, this); // 创建树的右键菜单
        this.setViewportView(this.tree);
        // 添加鼠标监听
        tree.addMouseListener(new MouseAdapter() {

            @Override
            public void mousePressed(MouseEvent e) {
                // 无论是左键还是右键点击都选中这条数据
                LeftPane.this.setSelectionPath(e);
                LeftPane.this.clickTreeNode();

                if (e.getModifiers() == MouseEvent.BUTTON3_MASK) {
                    // 右键点击，弹出菜单
                    // System.out.println("鼠标右键点击");
                    LeftPane.this.treeMenu.showTreeMenu(e);
                } else if (e.getModifiers() == MouseEvent.BUTTON1_MASK && e.getClickCount() == 2) {
                    // 左键双击
                    LeftPane.this.doubleClickTreeNode();

                }
            }
        });
    }

    // 创建树
    protected void createTree() {
        DefaultMutableTreeNode root = new DefaultMutableTreeNode(new RootNode());
        // 创建连接节点
        createNodes(root);
        this.treeModel = new DefaultTreeModel(root);
        // 构造树
        JTree tree = new JTree(this.treeModel);
        tree.setRowHeight(30);
        tree.setShowsRootHandles(true);//是否显示句柄
        tree.setCellRenderer(new DefaultTreeCellRenderer() {
            @Override
            public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
                // 设置背景色
                Color focusGainedColor = UIManager.getColor("Tree.focusGainedBackground") == null ?
                        new Color(205, 232, 255) : UIManager.getColor("Tree.focusGainedBackground"); // 聚焦时的背景色
                Color focusLostColor = UIManager.getColor("Tree.focusLostBackground") == null ?
                        new Color(213, 213, 213) : UIManager.getColor("Tree.focusLostBackground"); // 失去焦点时的背景色
               JLabel label = (JLabel) super.getTreeCellRendererComponent(
                        tree, value, selected, expanded, leaf, row, hasFocus);
                if (hasFocus) {
                    label.setBackground(selected ? focusGainedColor : tree.getBackground());
                } else {
                    label.setBackground(selected ? focusLostColor : tree.getBackground());
                }
                label.setOpaque(true);

                // 设置每个节点的图标
                DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
                // 获取每个节点的ViewObject
                ViewObject obj = (ViewObject) node.getUserObject();
                if (obj == null) return this;
                // 设置图片与文件
                label.setText(obj.toString());
                label.setIcon(obj.getIcon());
                return label;
            }
        });
        tree.setRootVisible(false); // 不显示根结点
        tree.setShowsRootHandles(true); // 设置显示句柄
        this.tree = tree;
    }

    // 创建树中服务器连接的节点
    private void createNodes(DefaultMutableTreeNode root) {
        Map<String, ServerConnection> scs = this.ctx.getAllSC();
        // 按字母排序，不区分大小写，前面相同按长度排序
        List<String> nameList = ctx.getSortNameList();
        for (String name : nameList) {
            ServerConnection sc = scs.get(name);
            // 创建连接节点
            DefaultMutableTreeNode scNode = new DefaultMutableTreeNode(sc);
            root.add(scNode);
        }
    }

    // 添加连接后刷新节点树
    protected void addSCNode(ServerConnection sc) {
        // 得到节点
        DefaultMutableTreeNode root = (DefaultMutableTreeNode) this.treeModel.getRoot();
        DefaultMutableTreeNode newChild = new DefaultMutableTreeNode(sc);
        // 往树中添加连接节点
        int index = ctx.getSortNameList().indexOf(sc.getName()); // 获取序号
        this.treeModel.insertNodeInto(newChild, root, index); // 插入节点
        this.treeModel.reload(); // 重新加载一次 treeModel，不能用 updateUI，否则可能会有 BUG，比如双击无法展开
        this.tree.setSelectionRow(index); // 设置选择新创建的节点
        this.tree.requestFocus(); // 设置焦点
        setObjectPaneData(null);
    }

    // 添加数据库后刷新节点数
    public void addDatabaseNode(Database database, int index) {
        // 获取选中的节点
        DefaultMutableTreeNode selectNode = this.getSelectNode();
        DefaultMutableTreeNode newChild = new DefaultMutableTreeNode(database);
        // 往服务器连接节点中添加新的数据库节点
        this.treeModel.insertNodeInto(newChild, selectNode, index);
    }

    // 左键单击节点操作
    private void clickTreeNode() {
        DefaultMutableTreeNode selectNode = this.getSelectNode();
        setObjectPaneData(selectNode);
    }

    // 设置对象面板的数据
    public void setObjectPaneData(DefaultMutableTreeNode selectNode) {
        // 右边面板赋值
        rightPane = mainFrame.getRightPane();
        if (selectNode == null) {
            rightPane.setObjectPaneData(emptyObjects);
            return;
        }
        Object node = selectNode.getUserObject();
        if (node == null) {
            rightPane.setObjectPaneData(emptyObjects);
            return;
        }
        // 清空右边面板数据
        if (node instanceof ServerConnection) {
            // 服务器连接节点
            objects = emptyObjects;
        } else if (node instanceof Database) {
            // 数据库节点
            Database db = (Database) node;
            if (db.getConnection() == null) {
                objects = emptyObjects;
            } else {
                objects = db.getTables().toArray();
            }
        } else if (node instanceof TableGroup) {
            // 表单分类节点
            TableGroup tableGroup = (TableGroup) node;
            objects = tableGroup.getDatabase().getTables().toArray();
        } else if (node instanceof ViewGroup) {
            // 视图分类节点
            ViewGroup viewGroup = (ViewGroup) node;
            objects = viewGroup.getDatabase().getViews().toArray();
        } else if (node instanceof ProcedureGroup) {
            // 存储过程分类节点
            ProcedureGroup procedureGroup = (ProcedureGroup) node;
            objects = procedureGroup.getDatabase().getProcedures().toArray();
        } else if (node instanceof Table) {
            // 表单节点
            Table table = (Table) node;
            objects = table.getDatabase().getTables().toArray();
        } else if (node instanceof View) {
            // 视图节点
            View view = (View) node;
            objects = view.getDatabase().getViews().toArray();
        } else if (node instanceof Procedure) {
            // 存储过程节点
            Procedure procedure = (Procedure) node;
            objects = procedure.getDatabase().getProcedures().toArray();
        }
        // 刷新对象面板的数据
        rightPane.setObjectPaneData(objects);
    }

    // 左键双击树节点的操作
    public void doubleClickTreeNode() {
        // 获取选中的节点
        DefaultMutableTreeNode selectNode = this.getSelectNode();
        if (selectNode == null) return;
        // 清空右边面板数据
        if (selectNode.getUserObject() instanceof ServerConnection) {
            // 双击服务器连接节点
            openServerNode(selectNode);
        } else if (selectNode.getUserObject() instanceof Database) {
            // 如果已经创建子节点，直接返回
            if (selectNode.getChildCount() != 0) return;
            // 否则创建子节点树
            openDatabaseNode(selectNode);
        } else if (selectNode.getUserObject() instanceof Table) {
            // 双击表单节点
            Table table = (Table) selectNode.getUserObject();
            rightPane.showTableData(table);
        }
        setObjectPaneData(selectNode);
    }

    // 双击服务器节点
    protected void openServerNode(DefaultMutableTreeNode selectNode) {
        ServerConnection sc = (ServerConnection) selectNode.getUserObject();
        validateConnect(sc, selectNode);
        // 创建服务器子节点
        buildServerChild(sc, selectNode);
        // 双击后自动展开子节点
        LeftPane.this.expandTreeNode();
    }

    // 双击数据库节点
    protected void openDatabaseNode(DefaultMutableTreeNode selectNode) {
        // 获取点击树节点的对象
        Database database = (Database) selectNode.getUserObject();
        validateConnect(database, selectNode);
        // 创建数据库下面的节点
        buildDatabaseChild(database, selectNode);
        // 双击后自动展开子节点
        LeftPane.this.expandTreeNode();
    }

    // 判断是否能正常连接
    private void validateConnect(ConnectionNode node, DefaultMutableTreeNode selectNode) {
        try {
            // 进行连接
            node.connect();
        } catch (Exception e) {
            //throw new RuntimeException("无法进行连接！");
            JOptionPane.showMessageDialog(mainFrame, "连接异常：" + e.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
        }
    }

    // 创建数据库第一层节点（树的第二层）
    private void buildServerChild(ServerConnection sc, DefaultMutableTreeNode selectNode) {
        // 如果有子节点，则不再创建
        if (selectNode.getChildCount() != 0) return;
        // 列出该连接下的所有数据库
        List<Database> databases = sc.getDatabases();
        // 再创建连接节点下面的所有的数据节点
        for (Database database : databases) {
            DefaultMutableTreeNode databaseNode = new DefaultMutableTreeNode(database);
            // 将数据库节点加入到连接节点中
            this.treeModel.insertNodeInto(databaseNode, selectNode, selectNode.getChildCount());
        }
    }

    // 创建数据库下面的节点（树的第三层）
    private void buildDatabaseChild(Database database, DefaultMutableTreeNode selectNode) {
        // 创建三个子节点（表、视图、存储过程）
        TableGroup tableGroup = new TableGroup(database);
        ViewGroup viewGroup = new ViewGroup(database);
        ProcedureGroup procedureGroup = new ProcedureGroup(database);
        DefaultMutableTreeNode tableGroupNode = new DefaultMutableTreeNode(tableGroup);
        DefaultMutableTreeNode viewGroupNode = new DefaultMutableTreeNode(viewGroup);
        DefaultMutableTreeNode procedureGroupNode = new DefaultMutableTreeNode(procedureGroup);
        // 将三个节点插入树中
        this.treeModel.insertNodeInto(tableGroupNode, selectNode, selectNode.getChildCount());
        this.treeModel.insertNodeInto(viewGroupNode, selectNode, selectNode.getChildCount());
        this.treeModel.insertNodeInto(procedureGroupNode, selectNode, selectNode.getChildCount());
        // 创建三个节点的子节点
        buildTableNode(tableGroup, tableGroupNode);
        buildViewNode(viewGroup, viewGroupNode);
        buildProcedureNode(procedureGroup, procedureGroupNode);
    }

    // 列出表单组下的所有表单（树的第四层）
    private void buildTableNode(TableGroup tableGroupNode, DefaultMutableTreeNode selectNode) {
        // 列出数据库下的所有表单
        List<Table> tables = tableGroupNode.getDatabase().getTables();
        for (Table tableNode : tables) {
            DefaultMutableTreeNode table = new DefaultMutableTreeNode(tableNode);
            this.treeModel.insertNodeInto(table, selectNode, selectNode.getChildCount());
        }
    }

    // 列出视图组下的所有视图（树的第四层）
    private void buildViewNode(ViewGroup viewGroupNode, DefaultMutableTreeNode selectNode) {
        // 列出数据库下的所有表单
        List<View> views = viewGroupNode.getDatabase().getViews();
        for (View viewNode : views) {
            DefaultMutableTreeNode view = new DefaultMutableTreeNode(viewNode);
            this.treeModel.insertNodeInto(view, selectNode, selectNode.getChildCount());
        }
    }

    // 列出存储过程组下的所有存储过程（树的第四层）
    private void buildProcedureNode(ProcedureGroup procedureGroup, DefaultMutableTreeNode selectNode) {
        // 列出数据库下的所有表单
        List<Procedure> procedures = procedureGroup.getDatabase().getProcedures();
        for (Procedure procedureNode : procedures) {
            DefaultMutableTreeNode procedure = new DefaultMutableTreeNode(procedureNode);
            this.treeModel.insertNodeInto(procedure, selectNode, selectNode.getChildCount());
        }
    }

    // 获得树中选中的节点
    protected DefaultMutableTreeNode getSelectNode() {
        TreePath treePath = this.tree.getSelectionPath();
        if (treePath == null) return null;
        // 获得选中的节点
        return (DefaultMutableTreeNode) treePath.getLastPathComponent();
    }

    // 设置右键位置选中
    protected void setSelectionPath(MouseEvent e) {
        TreePath path = LeftPane.this.tree.getPathForLocation(e.getX(), e.getY());
        if (path == null) return;
        LeftPane.this.tree.setSelectionPath(path);
    }

    // 刷新服务连接节点
    protected void refreshSCNode(ServerConnection sc) {
        DefaultMutableTreeNode selectNode = this.getSelectNode();
        selectNode.setUserObject(sc);
        this.treeModel.reload(); // 修改了 TreeNode 之后，调用此方法刷新
    }

    // 展开节点
    protected void expandTreeNode() {
        TreePath path = this.tree.getSelectionPath();
        this.tree.expandPath(path);
    }
}
